
from apps.goods.models import SKU, GoodsCategory, SPU, SPUSpecification, SpecificationOption, SKUSpecification
from rest_framework import serializers
from celery_tasks.html.tasks import generate_static_sku_detail_html
from django.db import transaction


# 规格详情序列化器
class SKUSpecSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ['spec_id', 'option_id']


class SKUSerializer(serializers.ModelSerializer):

    spu = serializers.StringRelatedField(read_only=True)
    category = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()

    specs = SKUSpecSerializer(many=True)
    class Meta:
        model = SKU
        fields = '__all__'

    def create(self, validated_data):
        # 将规格列表pop出来
        specs = validated_data.pop('specs')
        # 使用事务保证数据修改的完成性
        with transaction.atomic():
            save_point1 = transaction.savepoint() # 创建事务保存点
            try:
                # 将剩余的的字典数据添加到tb_sku表中
                sku = SKU.objects.create(**validated_data)
                sku.default_image = '/group1/M00/00/02/wKgDCl5IwS2EMFPCAAAAAN5_F7w0717882'
                sku.save()
                # 将分离开的列表数据添加到tb_sku_specification表中
                for i in specs:
                    SKUSpecification.objects.create(sku=sku, **i)
            except Exception:
                transaction.savepoint_rollback(save_point1) # 若出现异常则回滚
                return serializers.ValidationError('数据库错误')
            transaction.savepoint_commit(save_point1) # 若没有异常则提交保存到数据库
            # 调用异步celery
            generate_static_sku_detail_html.delay(sku.id)
            return sku


    def update(self, instance, validated_data):
        '''编辑SKU信息'''
        # 将规格列表pop出来
        specs = validated_data.pop('specs')
        # 创建事务保证数据存储的完整性
        with transaction.atomic():
            save_point2 = transaction.savepoint() #创建保存点
            try:
                # 调用父类的update方法
                sku = super().update(instance, validated_data)
                # 将取出的specs列表数据添加到tb_sku_specification表中
                for i in specs:
                    SKUSpecification.objects.filter(sku_id=instance.id, spec=i.get('spec_id')).update(
                        option=i.get('option_id')
                    )
            except Exception:
                transaction.savepoint_rollback(save_point2) # 若出现异常则回滚
                return serializers.ValidationError('数据错误')
            transaction.savepoint_commit(save_point2) #若未出现异常则正常保存
            # 调用异步celery
            generate_static_sku_detail_html.delay(sku.id)
            return sku




# 展示左右三级品类序列化器
class SKUCategorieSerializer(serializers.ModelSerializer):

    class Meta:
        model = GoodsCategory
        fields = "__all__"


# 根据三级品类查找所对应的spu商品名称的序列化器
class SPUSimpleModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = SPU
        fields = ['id', 'name']


# 获取选项中的规格值序列化器
class SpecOptSerializer(serializers.ModelSerializer):

    class Meta:
        model = SpecificationOption
        fields = ['id', 'value']


# 获取选项序列化器
class SPUSpeSerializer(serializers.ModelSerializer):
    options = SpecOptSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = '__all__'


